/*
 * cli.c
 *
 *  Created on: 2012-10-25
 *      Author: baronw
 */


#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <errno.h>
#include <limits.h>
#include <string.h>
#include <fcntl.h>

#include <ev.h>

#include "tlog.h"

/* A simple fifo program for user to attach the debug console */

typedef enum{
    SUB_TABLE,
    RUN_CMD,
}CLI_CMD_TYPE;

typedef struct {
    char            _cmd;
    CLI_CMD_TYPE    _type;
    void*           _action;
    char*           _help;
    char*           _promt_str;
}cli_cmd;

#define CMD_EOF_ENTRY \
    { '\0', RUN_CMD, NULL, NULL, NULL }

void hello(){
    printf("i am a tester\n");
}

cli_cmd sub_menu[] = {
    {'c', RUN_CMD, (void *) hello,
        NULL, "Test submenu function"},
    CMD_EOF_ENTRY

};

cli_cmd test_func[] = {
    {'a', RUN_CMD, (void *) hello,
        NULL, "Test function"},
    {'b', SUB_TABLE, (void *) sub_menu,
        NULL, "Test submenu"},
    CMD_EOF_ENTRY
};


static const char* __in_fifo_name;
static const char* __out_fifo_name;
static const char* __err_fifo_name;

typedef struct{
    pthread_t       tid;
    int             in_fd;
    int             p[2];
    struct ev_loop  *loop;
    struct ev_io    p_ev;
    struct ev_io    in_ev;
}cli_thread;

static cli_thread __cli_info;

static char __read_from_fifo(int fifo_fd){

    return ' ';
}

static int __write_output(int fifo_fd){

    return 0;
}

static int __write_error(){

    return 0;
}


static void __pipe_callback (struct ev_loop *loop, ev_io *w, int rev){

    register int res;
    char buf[16];

    if(rev | EV_READ){
        /* read bytes to empty the thread pipe */
        while((res = read(__cli_info.p[0], buf, sizeof(buf))) == sizeof(buf)){
            ;
        }
    }else{
        LOG(_WRN, "get an error event.");
    }

    return;
}

static void __in_fifo_callback(struct ev_loop *loop, ev_io *w, int rev){

    static int p_flags = 0;


    /* very likely to hit here */
    if(rev | EV_READ){


        return;
    }else{
        LOG(_WRN, "get an error event for fifo.");
    }

    return;
}


void * __cli_loop(void* args){

    struct ev_io *pio = &(__cli_info.p_ev);
    struct ev_io *p_fifo_io = &(__cli_info.in_ev);

    /* 1, init the pipe for wake-up the cli process */
    if(-1 == pipe(__cli_info.p)){
        LOG(_CRI, "fail to create pipe for cli thread, reason: %d(%s)."
            , errno, strerror(errno));
        return NULL;
    }

    if(fcntl(__cli_info.p[0], F_SETFL, O_NONBLOCK) ||
        fcntl(__cli_info.p[1], F_SETFL, O_NONBLOCK)){
        LOG(_CRI, "fail to set pipes to non-blocking mode in cli thread reason:"
            " %d(%s).", errno, strerror(errno));
        return NULL;
    }

    __cli_info.loop = ev_loop_new(EVFLAG_AUTO);

    /* 2, the pipe can be waken, but need to set to ev loop */
    ev_init(pio, __pipe_callback);
    ev_io_set(pio, __cli_info.p[0], EV_READ | EV_WRITE);
    ev_io_start(__cli_info.loop, pio);


    /* 3, add the input fd into the loop */
    ev_init(p_fifo_io, __in_fifo_callback);
    ev_io_set(p_fifo_io, __cli_info.in_fd, EV_READ | EV_ERROR);
    ev_io_start(__cli_info.loop, p_fifo_io);

    /* infinate loop untils loop breaks */
    ev_run(__cli_info.loop, 0);

    /* release the pipe */
    close(__cli_info.p[0]);
    close(__cli_info.p[1]);

    pthread_detach(__cli_info.tid);

    return NULL;
}

